﻿Imports System.IO
Imports System.Net
Imports System.Text

Public Class FileListForm


    Private fileNameList As New ArrayList
    ' ソースファイルリスト
    Private sourceFileList As New ArrayList

    Public isFromTree As Boolean = False
    Public matchingFilePath As String
    Public matchingFileList As New ArrayList


    Public isPresets As Boolean = False

    Private iniFileName As String = "EasyExportFiles.ini"

    Private PROJECT_PATH As String = "PROJECT_PATH"
    Private PROJECT_FILES As String = "PICK_FILES"


    ''' <summary>
    ''' 画面初期化
    ''' </summary>
    ''' <param name="sender"></param>    
    ''' <param name="e"></param>
    Private Sub FileListForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        '
        Dim sectionList As New ArrayList
        sectionList = IniFile.GetSections(Path.Combine(Application.StartupPath, Me.iniFileName))
        Me.cbProjectNames.Items.Clear()
        Me.cbProjectNames.Items.AddRange(sectionList.ToArray)

        If Me.matchingFileList.Count = 0 Then

        Else
            RemoveHandler Me.txtFilePath.TextChanged, AddressOf Me.txtFilePath_TextChanged
            Me.txtFilePath.Text = matchingFilePath
            AddHandler Me.txtFilePath.TextChanged, AddressOf Me.txtFilePath_TextChanged

            Call ResetFileList()
        End If

    End Sub



    ''' <summary>
    ''' 
    ''' </summary>
    ''' <returns></returns>
    Private Function GetMatchingFileList() As ArrayList

        Dim strMatchingFiles As String
        strMatchingFiles = IniFile.ReadIniValue(Path.Combine(Application.StartupPath, Me.iniFileName), Me.cbProjectNames.Text, Me.PROJECT_FILES)

        Dim mfList As New ArrayList


        For Each str As String In strMatchingFiles.Split("?")

            Dim mf As New MatchingFile

            Dim kv() As String
            kv = str.Split("<")

            mf.fileName = kv(0)

            For Each paths As String In kv(1).Split(">")

                mf.filePath.Add(paths)

            Next

            mfList.Add(mf)
        Next


        GetMatchingFileList = mfList
    End Function


    ''' <summary>
    ''' ファイル名リストを再設定する。
    ''' </summary>
    Private Sub ResetFileList()

        Me.dgvFileList.Rows.Clear()

        For Each item As MatchingFile In Me.matchingFileList
            Dim dgvr As New DataGridViewRow

            ' 確定
            Dim cellIsOK As New DataGridViewButtonCell()
            cellIsOK.Value = IIf(item.filePath.Count = 1, "確定", "未確定")

            dgvr.Cells.Add(cellIsOK)

            ' ファイル名
            Dim cellFileName As New DataGridViewTextBoxCell()
            cellFileName.Value = item.fileName
            dgvr.Cells.Add(cellFileName)

            ' ファイルフールパス
            Dim cellFileFullPath As New DataGridViewTextBoxCell()

            If item.filePath.Count = 1 Then
                'cellFileFullPath.Style.BackColor = Color.Yellow
                cellFileFullPath.Value = item.filePath.Item(0)
            Else
                cellFileFullPath.Style.BackColor = Color.Yellow
                cellFileFullPath.Value = ""
            End If

            dgvr.Cells.Add(cellFileFullPath)

            Me.dgvFileList.Rows.Add(dgvr)
        Next

        ' 画面ファイル数表示
        Me.lblTotal.Text = Me.dgvFileList.RowCount.ToString() + " ファイル"

    End Sub


    ''' <summary>
    ''' ファイル名リストインポート
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnImport_Click(sender As Object, e As EventArgs) Handles btnImport.Click

        If Not Directory.Exists(Me.txtFilePath.Text) Then
            Return
        End If

        Using importForm As New ImportForm
            importForm.ShowDialog(Me)

            If importForm.fileNameList.Count = 0 Then
                ' nop
            Else
                ' インポート画面から選択ありの場合、ファイルリストを更新する。
                Me.fileNameList = importForm.fileNameList

                Me.sourceFileList = New ArrayList

                Call GetAllFilesInFolder(Me.txtFilePath.Text, Me.sourceFileList)

                Me.matchingFileList = FindAllSource()

                ' 再表示
                Call ResetFileList()
            End If
        End Using
    End Sub

    Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click


        If countNotConfirm() > 0 OrElse Me.dgvFileList.Rows.Count = 0 Then
            MsgBox("must be export files after confirm for all exists files")
            Return
        End If

        Dim strExportSubPath As String
        Dim strExportPath As String

        strExportSubPath = ""

        strExportPath = Application.StartupPath & "\Export_" & Format(Now(), "yyyyMMddhhmmss")

        'プログレスバー
        Me.pgb.Minimum = 0
        Me.pgb.Maximum = Me.dgvFileList.RowCount
        Me.pgb.Value = 0
        Me.Enabled = False

        For Each mf As MatchingFile In Me.matchingFileList

            Dim strFilePath As String
            Dim strFolderPath As String

            strFilePath = Replace(mf.filePath.Item(0), Me.txtFilePath.Text, "")
            strFolderPath = Path.GetDirectoryName(strExportPath + strFilePath)

            If Not Directory.Exists(strFolderPath) Then

                Directory.CreateDirectory(strFolderPath)
            End If

            File.Copy(mf.filePath.Item(0), strExportPath + strFilePath)

            Me.pgb.Value = Me.pgb.Value + 1

        Next
        Me.Enabled = True
        Shell("explorer " & strExportPath, vbNormalFocus)

    End Sub

    Private Function FindAllSource() As ArrayList

        Dim resultList As New ArrayList

        For Each targetFile As String In Me.fileNameList


            If String.IsNullOrEmpty(targetFile) Then
                Continue For
            End If

            Dim mf As New MatchingFile

            If hasDirectory(targetFile) AndAlso File.Exists(Path.Combine(Me.txtFilePath.Text, targetFile)) Then

                ' ファイル名を取得
                mf.fileName = targetFile.Substring(targetFile.LastIndexOf("\") + 1)

                mf.filePath.Add(Path.Combine(Me.txtFilePath.Text, targetFile))
                resultList.Add(mf)
            Else

                For Each sourceFile As String In Me.sourceFileList
                    Dim fName As String
                    fName = Path.GetFileName(sourceFile)

                    If fName.Equals(targetFile) Then

                        mf.fileName = fName
                        mf.filePath.Add(sourceFile)

                    End If
                Next

                If Not String.IsNullOrEmpty(mf.fileName) Then
                    resultList.Add(mf)
                Else
                    mf.fileName = targetFile
                    resultList.Add(mf)
                End If

            End If
            mf = Nothing
        Next

        Return resultList
    End Function

    ''' <summary>
    ''' ディレクトリであるか
    ''' </summary>
    ''' <param name="fName"></param>
    ''' <returns></returns>
    Private Function hasDirectory(ByVal fName As String) As Boolean


        Return （fName.IndexOf("\") > 0)

    End Function


    Private Sub dgvFileList_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgvFileList.CellContentClick

        ' 未確定ボタン押下する時
        If Me.dgvFileList.SelectedCells.Item(0).ColumnIndex = 0 Then

            Dim mf As New MatchingFile
            ' 選択したソース情報取得
            mf = Me.matchingFileList.Item(Me.dgvFileList.SelectedCells.Item(0).RowIndex)

            If mf.filePath.Count = 0 Then
                MsgBox("can not confirm ")
            Else
                Using pf As New PickForm
                    ' 選択したソース情報を渡す
                    pf.mf = mf
                    Call pf.ShowDialog()

                    If pf.newList.Count = 0 Then
                    Else
                        ' 渡したソースをリストから外す
                        Me.matchingFileList.Remove(mf)
                        ' ユーザが確定された後のソースをリストに追加
                        For Each newPr As MatchingFile In pf.newList

                            Me.matchingFileList.Insert(Me.dgvFileList.SelectedCells.Item(0).RowIndex, newPr)
                        Next

                        Call ResetFileList()
                    End If
                End Using

            End If

        End If
    End Sub


    Sub GetAllFilesInFolder(ByVal folderPath As String, ByRef fileList As ArrayList)
        Try
            ' 获取当前文件夹下的所有文件
            Dim filesInFolder As String() = Directory.GetFiles(folderPath)
            fileList.AddRange(filesInFolder)

            ' 获取当前文件夹下的所有子文件夹
            Dim subFolders As String() = Directory.GetDirectories(folderPath)
            For Each subFolder In subFolders
                GetAllFilesInFolder(subFolder, fileList)
            Next
        Catch ex As Exception
            Console.WriteLine($"Error: {ex.Message}")
        End Try
    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click

        If countNotConfirm() > 0 Then
            MsgBox("must be add new file after confirm for all exists files")
            Return
        End If

        Me.OpenFileDialog1.InitialDirectory = Me.txtFilePath.Text

        Dim mf As New MatchingFile
        If Me.OpenFileDialog1.ShowDialog() = DialogResult.OK Then

            Dim strTemp As String
            strTemp = Me.OpenFileDialog1.FileName

            mf.fileName = Path.GetFileName(Me.OpenFileDialog1.FileName)
            mf.filePath.Add(Me.OpenFileDialog1.FileName)

            If isExistsFile(mf) Then

                MsgBox("you are selected a exsits file")
                Return
            End If

            If strTemp.IndexOf(Me.txtFilePath.Text) >= 0 Then

                Me.matchingFileList.Add(mf)
                Call ResetFileList()
            Else
                MsgBox("must be select from directory:[" + Me.txtFilePath.Text + "]")
            End If
        End If

    End Sub

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnUpd_Click(sender As Object, e As EventArgs) Handles btnUpd.Click

        If countNotConfirm() > 0 Then
            MsgBox("must be upd a file after confirm for all exists files")
            Return
        End If

        ' can not upd from non list!
        If Me.dgvFileList.Rows.Count = 0 Then
            Return
        End If

        Dim rowIndex As Integer
        rowIndex = Me.dgvFileList.SelectedCells.Item(0).RowIndex

        Me.OpenFileDialog1.InitialDirectory = Me.txtFilePath.Text

        Dim mf As New MatchingFile
        If Me.OpenFileDialog1.ShowDialog() = DialogResult.OK Then

            Dim strTemp As String
            strTemp = Me.OpenFileDialog1.FileName

            mf.fileName = Path.GetFileName(Me.OpenFileDialog1.FileName)
            mf.filePath.Add(Me.OpenFileDialog1.FileName)


            If isExistsFile(mf) Then

                MsgBox("you are selected a exsits file")
                Return
            End If

            If strTemp.IndexOf(Me.txtFilePath.Text) >= 0 Then

                Me.matchingFileList.RemoveAt(rowIndex)
                Me.matchingFileList.Insert(rowIndex, mf)
                Call ResetFileList()
            Else
                MsgBox("must be select from directory:[" + Me.txtFilePath.Text + "]")
                Return
            End If

        End If

    End Sub

    Private Sub btnDel_Click(sender As Object, e As EventArgs) Handles btnDel.Click

        If Me.dgvFileList.Rows.Count = 0 Then

            Return
        End If

        Dim rowIndex As Integer
        rowIndex = Me.dgvFileList.SelectedCells.Item(0).RowIndex
        If rowIndex >= 0 Then
            Me.matchingFileList.RemoveAt(rowIndex)
            Call ResetFileList()
        End If

    End Sub

    ''' <summary>
    ''' 未確定数を返す
    ''' </summary>
    ''' <returns></returns>
    Private Function countNotConfirm() As Integer
        Dim iCnt As Integer = 0
        For i As Integer = 0 To Me.dgvFileList.Rows.Count - 1

            Dim cellIsOK As New DataGridViewButtonCell()

            cellIsOK = Me.dgvFileList.Rows.Item(i).Cells(0)

            If "未確定".Equals(cellIsOK.Value) Then
                iCnt = iCnt + 1
            End If
        Next
        countNotConfirm = iCnt
    End Function


    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="mf"></param>
    ''' <returns></returns>
    Private Function isExistsFile(ByVal mf As MatchingFile) As Boolean

        Dim isExists As Boolean = False

        For Each tmp As MatchingFile In Me.matchingFileList

            If tmp.fileName.Equals(mf.fileName) AndAlso tmp.filePath.Count = mf.filePath.Count Then

                If tmp.filePath.Item(0) = mf.filePath.Item(0) Then
                    isExists = True
                    Exit For
                End If

            End If

        Next
        isExistsFile = isExists
    End Function

    Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click

        If String.IsNullOrEmpty(Me.cbProjectNames.Text) Then
            MsgBox("must be input a new project name!")
            Return
        End If

        If Me.cbProjectNames.Items.Contains(Me.cbProjectNames.Text) Then

            If MessageBox.Show("do you really wanna overide?", "overide confirm", MessageBoxButtons.YesNo) = DialogResult.No Then
                Return
            End If
        End If

        Dim strTemp As New StringBuilder

        For Each mf As MatchingFile In Me.matchingFileList


            If Not strTemp.Length = 0 Then
                strTemp.Append("?")
            End If
            strTemp.Append(mf.fileName)
            strTemp.Append("<")

            Dim strPaths As New StringBuilder
            For Each str As String In mf.filePath

                If Not strPaths.Length = 0 Then
                    strPaths.Append(">")
                End If

                strPaths.Append(str)
            Next

            strTemp.Append(strPaths.ToString())

        Next

        '
        Call IniFile.WriteIniValue(Path.Combine(Application.StartupPath, Me.iniFileName),
                              Me.cbProjectNames.Text,
                              Me.PROJECT_PATH,
                              Me.txtFilePath.Text)

        Call IniFile.WriteIniValue(Path.Combine(Application.StartupPath, Me.iniFileName),
                              Me.cbProjectNames.Text,
                              Me.PROJECT_FILES,
                              strTemp.ToString())

        '
        Dim sectionList As New ArrayList
        sectionList = IniFile.GetSections(Path.Combine(Application.StartupPath, Me.iniFileName))

        Me.cbProjectNames.Items.Clear()
        Me.cbProjectNames.Items.AddRange(sectionList.ToArray)

        MsgBox("saved！")
    End Sub

    Private Sub txtFilePath_DoubleClick(sender As Object, e As EventArgs) Handles txtFilePath.DoubleClick

        Dim strResult As String
        strResult = FolderBrowserDialog1.ShowDialog(Me)

        If Not Me.txtFilePath.Text = FolderBrowserDialog1.SelectedPath And Not Trim(FolderBrowserDialog1.SelectedPath) = "" Then

            Me.txtFilePath.Text = FolderBrowserDialog1.SelectedPath
            'Call ReadNewFolder()

        End If

    End Sub

    Private Sub cbProjectNames_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cbProjectNames.SelectedIndexChanged

        RemoveHandler Me.txtFilePath.TextChanged, AddressOf Me.txtFilePath_TextChanged

        If String.IsNullOrEmpty(Me.cbProjectNames.Text) Then
            Return
        End If

        Me.txtFilePath.Text = IniFile.ReadIniValue(Path.Combine(Application.StartupPath, Me.iniFileName), Me.cbProjectNames.Text, Me.PROJECT_PATH)

        Me.matchingFileList = GetMatchingFileList()

        Call ResetFileList()

        AddHandler Me.txtFilePath.TextChanged, AddressOf Me.txtFilePath_TextChanged

    End Sub

    Private Sub btnBrows_Click(sender As Object, e As EventArgs) Handles btnBrows.Click
        Call txtFilePath_DoubleClick(sender, e)
    End Sub


    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Public Sub txtFilePath_TextChanged(sender As Object, e As EventArgs) Handles txtFilePath.TextChanged

        RemoveHandler Me.cbProjectNames.SelectedIndexChanged, AddressOf Me.cbProjectNames_SelectedIndexChanged

        Me.cbProjectNames.Text = ""

        Me.fileNameList = GetFileNameList()

        Me.sourceFileList = New ArrayList
        Call GetAllFilesInFolder(Me.txtFilePath.Text, Me.sourceFileList)

        Me.matchingFileList = FindAllSource()

        ' 再表示
        Call ResetFileList()

        AddHandler Me.cbProjectNames.SelectedIndexChanged, AddressOf Me.cbProjectNames_SelectedIndexChanged

    End Sub

    Private Function GetFileNameList() As ArrayList
        Dim list As New ArrayList

        For Each mf As MatchingFile In Me.matchingFileList
            If Not list.Contains(mf.fileName) Then
                list.Add(mf.fileName)
            End If

        Next
        GetFileNameList = list
    End Function

    Private Sub btnClose_Click(sender As Object, e As EventArgs) Handles btnClose.Click
        Me.Close()
    End Sub


End Class